#ifndef _INPUT_MANAGER_H_
#define _INPUT_MANAGER_H_

#include "../renderer/viewport.h"
#include "../shapes.h"

#include <map>
#include <boost/smart_ptr/shared_ptr.hpp>


class CInputManager
{
	class CMouseInput
	{
	private:
		boost::shared_ptr<CViewport> _vp;
		unsigned int _vpID;
		static int listenResize(const SRect & rect);
		SPoint _center_cln;
		SPoint _center_scr;

		union UMouseOffset
		{
			struct
			{
				short x;
				short y;
			}d;
			unsigned long mask;
			UMouseOffset(unsigned long val = 0):mask(val){}
			inline void set(short dx, short dy) volatile {d.x = dx; d.y = dy;}
		};

	public:
		CMouseInput();
		inline void attachViewport(const boost::shared_ptr<CViewport> & vp) {_vp = vp; _vpID = vp->attach(listenResize);}
		inline void detachViewport(void) {_vp->detach(_vpID);}

		inline void setScreenCenter(long x, long y) {_center_scr.x = x; _center_scr.y = y;}
		inline void setClientCenter(long x, long y) {_center_cln.x = x; _center_cln.y = y;}

		inline const SPoint & getScreenCenter() const {return _center_scr;}
		inline const SPoint & getClientCenter() const {return _center_cln;}
		void mouseMove(int dx, int dy);
		volatile UMouseOffset mousePos; // concurent access from input & render threads
	};

private:
	static CInputManager * _inst;
	CMouseInput _mouse;

protected:
	CInputManager();
	CInputManager(const CInputManager & r);
	CInputManager & operator = (const CInputManager & r);

public:
	inline static CInputManager * create() {return (_inst = new CInputManager());}
	inline static CInputManager * getInstance() {return _inst;}
	inline CMouseInput & getMouse() {return _mouse;}
};

#endif // _INPUT_MANAGER_H_